using System;
using System.Runtime.Serialization.Formatters;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AStar : MonoBehaviour
{
    [Header("[长]")]
    [Header("                              [网格格子尺寸]")]
    public float gridHorValue;
    [Header("[宽]")]
    public float gridVerValue;

    [Header("[长]")]
    [Header("                              [网格参数]")]
    public int horizontalValue;//横排数量
    [Header("[宽]")]
    public int verticalValue;//横排数量
    [SerializeField]
    [Header("                              [网格格子总数量]")]
    private int allGridValue = 0;

    [Header("                              [地板预制体]")]

    public GameObject floor;//地板预制体
    public Material floor0;//地板预制体
    public Material floor1;//地板预制体
    public Material floor2;//地板预制体
    public Material floor3;//地板预制体
    public Material floor4;//地板预制体
    public Material floor5;
    Material materialFloor;
    //public int[] startPlace;

    [Header("                              [起始位置]")]
    [Tooltip("[起始位置（长度为2的float类型数组变量，Size必须填入2，下面参数必须是float类型（小数）。第一个参数是X轴位置，第二个参数是Z轴位置）]")]
    public float[] startPosition = new float[2] { 0, 0 };



    int[] pavedSign;//铺设游标
    Vector3 pavedPositon;//铺设位置
    int floorSing;
    bool isFind;
    Dictionary<string, BaseGrid> GridDic = new Dictionary<string, BaseGrid>();

    PathData TargetPathData;
    void Start()
    {
        allGridValue = horizontalValue * verticalValue;
        pavedSign = new int[2] { 0, 0 };
        pavedPositon = new Vector3(startPosition[0], 0, startPosition[1]);
        floorSing = 0;
        DrawMap();//生成网格完成
        //GetAdjacentGrid();//格子相邻格子获取

        GridDic["4*4"].pathTag = "obstacle";
        GridDic["4*4"].ChangeMaterial(floor4);
        GridDic["3*4"].pathTag = "obstacle";
        GridDic["3*4"].ChangeMaterial(floor4);
        GridDic["2*4"].pathTag = "obstacle";
        GridDic["2*4"].ChangeMaterial(floor4);
        PathData startGrid = new PathData();
        startGrid.pathCy = new int[2] { 3, 2 };
        startGrid.pathaType = "startPath";
        startGrid.father = null;
        GridDic["3*2"].pathTag = "startPath";
        PathData endGrid = new PathData();
        endGrid.pathCy = new int[2] { 3, 6 };
        GridDic["3*6"].pathTag = "endPath";
        isFind = false;
        LookForPath(startGrid, endGrid);
        GetPathList();
        Debug.Log(PathStack.Count);
        foreach (var item in PathStack)
        {
            GridDic[item[0].ToString() + "*" + item[1].ToString()].ChangeMaterial(floor5);
            Debug.Log(item[0] + "  " + item[1]);
        }
    }
    void DrawMap()
    {
        if (startPosition.Length != 2)
        {
            Debug.LogError("起始位置数组参数长度非法，请输入正常长度参数");
        }
        else
        {
            for (int i = 0; i < verticalValue; i++)
            {
                for (int j = 0; j < horizontalValue; j++)
                {
                    if (floorSing % 2 == 0)
                    {
                        materialFloor = floor0;
                    }
                    else
                    {
                        materialFloor = floor1;
                    }
                    int[] gridSign = new int[] { i, j };
                    string sing = i.ToString() + "*" + j.ToString();
                    GridDic.Add(sing, new BaseGrid(floor, materialFloor, pavedPositon, transform, gridSign));
                    ++floorSing;
                    startPosition[0] = startPosition[0] + 1;
                    pavedPositon.x = pavedPositon.x + gridHorValue;
                }
                if (i == (verticalValue - 1))
                {
                    break;
                }
                //列 参数更新 与 重置 || 更新 列游标  重置 行游标
                startPosition[1] = startPosition[1] + 1;
                pavedPositon.z = pavedPositon.z + gridVerValue;
                pavedPositon.x = startPosition[0] - (horizontalValue * gridHorValue);
                startPosition[0] = pavedPositon.x;
            }
        }
    }
    List<PathData> openPathList = new List<PathData>(); //开表
    List<PathData> closePathList = new List<PathData>(); //闭表
    List<PathData> newPathList = new List<PathData>();
    string zhao;
    int numberOfSteps = 0;
    bool isMove = false;
    PathData boxPathData = new PathData(); //盒子 做调换的参数
    void LookForPath(PathData startGrid, PathData endGrid)
    {
        if (!isFind)
        {
            //寻找可走的路径点
            for (int i = startGrid.pathCy[0] + 1; i > startGrid.pathCy[0] - 2; i--)
            {
                for (int j = startGrid.pathCy[1] - 1; j < startGrid.pathCy[1] + 2; j++)
                {
                    zhao = i.ToString() + "*" + j.ToString();
                    if (GridDic.TryGetValue(zhao, out BaseGrid grid))
                    {
                        if (grid.pathTag == null || grid.pathTag == "endPath")
                        {
                            PathData pathData = new PathData();
                            pathData.name = numberOfSteps + "*" + i.ToString() + "*" + j.ToString();
                            pathData.father = new PathData();
                            pathData.father = startGrid;
                            pathData.pathCy = new int[] { i, j };
                            pathData.pathaType = "Path";
                            newPathList.Add(pathData);
                            GridDic[i.ToString() + "*" + j.ToString()].pathTag = i.ToString() + "*" + j.ToString();
                            GridDic[i.ToString() + "*" + j.ToString()].ChangeMaterial(floor3);
                        }
                    }

                }
            }
            //计算新路径点的消耗
            for (int i = 0; i < newPathList.Count; i++)
            {
                //子到父消耗
                if (newPathList[i].pathCy[0] == startGrid.pathCy[0] || newPathList[i].pathCy[1] == startGrid.pathCy[1])
                {
                    newPathList[i].fatherToMeCost = 1;
                }
                else
                {
                    newPathList[i].fatherToMeCost = 1.4f;
                }
                //子到起消耗 = 子到父+父消耗
                if (newPathList[i].father.pathaType == "startPath")
                {
                    newPathList[i].toStartCost = newPathList[i].fatherToMeCost;
                }
                else
                {
                    newPathList[i].toStartCost = newPathList[i].father.toStartCost + newPathList[i].fatherToMeCost;
                }
                float hangValue;
                float lieValue;
                //总消耗
                if (newPathList[i].pathCy[0] > endGrid.pathCy[0])
                {
                    hangValue = newPathList[i].pathCy[0] - endGrid.pathCy[0];
                }
                else
                {
                    hangValue = endGrid.pathCy[0] - newPathList[i].pathCy[0];
                }
                if (newPathList[i].pathCy[1] > endGrid.pathCy[1])
                {
                    lieValue = newPathList[i].pathCy[1] - endGrid.pathCy[1];
                }
                else
                {
                    lieValue = endGrid.pathCy[1] - newPathList[i].pathCy[1];
                }
                newPathList[i].toEndCost = hangValue + lieValue;
                newPathList[i].allCost = newPathList[i].toStartCost + newPathList[i].toEndCost;
            }

            openPathList.AddRange(newPathList);
            newPathList.Clear();
            for (int i = 0; i < openPathList.Count; i++)
            {
                // Debug.Log(openPathList[i].name+" "+openPathList[i].allCost);
            }
            isMove = true;
            //排序
            for (int i = 0; i < openPathList.Count; i++)
            {
                isMove = true;
                if (isMove)
                {
                    SortForOpenPathList();
                }
                else
                {
                    break;
                }
            }
            Debug.Log(openPathList[0].name + " " + openPathList[0].allCost);
            //Debug.Log(openPathList[0].father.name);
            TargetPathData = openPathList[0];
            closePathList.Add(openPathList[0]);//添加进闭包
            openPathList.RemoveAt(0); //从开包中移除
            if (TargetPathData.pathCy[0] == endGrid.pathCy[0] && TargetPathData.pathCy[1] == endGrid.pathCy[1])//当前路径是否为目标路径
            {
                isFind = true;
                GridDic[TargetPathData.pathCy[0].ToString() + "*" + TargetPathData.pathCy[1].ToString()].ChangeMaterial(floor4);
            }
            else
            {
                if (openPathList.Count <= 0)
                {
                    isMove = true;
                    Debug.Log("没有路");
                }
                else
                {
                    ++numberOfSteps;
                    LookForPath(TargetPathData, endGrid);
                }

            }
        }
    }

    //开列表排序
    void SortForOpenPathList()
    {

        for (int index1 = 0; index1 < openPathList.Count; index1++)
        {
            if (index1 + 1 != openPathList.Count)
            {
                if (openPathList[index1].allCost > openPathList[index1 + 1].allCost)
                {
                    isMove = true;
                    boxPathData = openPathList[index1];
                    openPathList[index1] = openPathList[index1 + 1];
                    openPathList[index1 + 1] = boxPathData;
                }
            }

        }
    }


    Stack<int[]> PathStack = new Stack<int[]>();
    void GetPathList()
    {
        PathStack.Push(TargetPathData.pathCy);
        while (TargetPathData.father != null)
        {
            PathStack.Push(TargetPathData.father.pathCy);
            TargetPathData = TargetPathData.father;
        }
    }

}